/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Juego;

import Controlador.Controlador;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Flor
 */
public class Partida {

    private Mesa mesa;
    private static Partida instancia;
    private Jugador Apostador = null;//jugador que tiene el turno
    private String Estapa = "preFlop";

    public static Partida darInstancia() {
        if (instancia == null) {
            instancia = new Partida();
        }
        return instancia;
    }
    //GETTERS AND SETTERS

    public Mesa getMesa() {
        return mesa;
    }

    public void setMesa(Mesa mesa) {
        this.mesa = mesa;
    }

    private Partida() {
    }

    public void inicializarJugadores(String nombre, String dif) {
        Jugador humano = new Jugador(nombre, "humano", false, null);

        Jugador maquina1 = new Jugador("Maquina1", dif, false, null);
        Jugador maquina2 = new Jugador("Maquina2", dif, false, null);
        Jugador maquina3 = new Jugador("Maquina3", dif, false, null);
        Jugador maquina4 = new Jugador("Maquina4", dif, false, null);
        Jugador maquina5 = new Jugador("Maquina5", dif, false, null);
        Jugador maquina6 = new Jugador("Maquina6", dif, false, null);
        Jugador maquina7 = new Jugador("Maquina7", dif, false, null);



        humano.setSigJugador(maquina1);
        maquina1.setSigJugador(maquina2);
        maquina2.setSigJugador(maquina3);
        maquina3.setSigJugador(maquina4);
        maquina4.setSigJugador(maquina5);
        maquina5.setSigJugador(maquina6);
        maquina6.setSigJugador(maquina7);
        maquina7.setSigJugador(humano);

        this.getMesa().agregarJugador(humano);
        this.getMesa().agregarJugador(maquina1);
        this.getMesa().agregarJugador(maquina2);
        this.getMesa().agregarJugador(maquina3);
        this.getMesa().agregarJugador(maquina4);
        this.getMesa().agregarJugador(maquina5);
        this.getMesa().agregarJugador(maquina6);
        this.getMesa().agregarJugador(maquina7);
    }

    public void iniciarPartida() {
        try {

            mesa.ocultarCartas();

            Jugador dealer = mesa.buscarDealer();
            if (dealer == null) {
                mesa.getLstJugadores().get(0).setDealer(true);
                mesa.setLstJugadores(mesa.getLstJugadores(), 0);
                dealer = mesa.buscarDealer();
            }

            apostarCiegas(dealer);
            preFlop(dealer.getSigJugador().getSigJugador(), false);
        } catch (Exception e) {
        }
    }

    public void apostarCiegas(Jugador dealer) {
        try {
            Controlador.darInstancia().mostrarMensaje("Se apuestan las ciegas");
            Jugador siguiente = mesa.buscarSiguienteActivo(dealer);
            if (siguiente.isActivo() == false) {
                ganador(mesa.buscarUltimoActivo());
            } else {

                mesa.apostarCiega(siguiente, 1);//ciega chica
                siguiente = mesa.buscarSiguienteActivo(siguiente);
                mesa.apostarCiega(siguiente, 2);//ciega grande
                mesa.setUltimoAp(siguiente);
            }
        } catch (Exception e) {
        }
    }

    public void terminarPartida(Jugador jugAux) {
        try {

            jugAux.setMontoDisponible(mesa.getPozo() + jugAux.getMontoDisponible());
            mesa.setPozo(0);
            mesa.setLstJugadores(mesa.getLstJugadores(), 0);
            Controlador.darInstancia().mostrarMensaje("Ganador de la Partida " + jugAux.getNombre() + "");


        } catch (Exception e) {
        }
    }

    public void ganador(List<Jugador> lstGanadores)//da como ganada la partida al jugador que se le pasa  y empieza una nueva mano
    {

        try {
            if (lstGanadores.size() == 1) {
                Controlador.darInstancia().mostrarMensaje("Ha Ganado la mano " + lstGanadores.get(0).getNombre());

                lstGanadores.get(0).setMontoDisponible(mesa.getPozo() + lstGanadores.get(0).getMontoDisponible());
                mesa.setMazo(new Mazo());
                mesa.cambiarDealer(mesa.buscarDealer().getSigJugador());
                mesa.activarJugadores();
                mesa.getLstCartas().removeAll(mesa.getLstCartas());
                mesa.setLstCartas(new ArrayList<Carta>());
                mesa.setPozo(0);
                mesa.setUltimoAp(null);

            } else {
                Controlador.darInstancia().mostrarMensaje("Hay un empate entre varios jugadores el Pozo se Dividira");

                if (lstGanadores.size() > 0) {
                    int aux = mesa.getPozo();
                    aux = aux / lstGanadores.size();
                    for (int i = 0; i < lstGanadores.size(); i++) {
                        lstGanadores.get(i).setMontoDisponible(lstGanadores.get(i).getMontoDisponible() + aux);
                    }
                }

                mesa.setMazo(new Mazo());
                mesa.cambiarDealer(mesa.buscarDealer().getSigJugador());
                mesa.activarJugadores();
                mesa.getLstCartas().removeAll(mesa.getLstCartas());
                mesa.setLstCartas(new ArrayList<Carta>());
                mesa.setPozo(0);
                mesa.setUltimoAp(null);
            }

            List<Jugador> lstJugadores = mesa.getLstJugadores();
            for (int i = 0;
                    i < lstJugadores.size();
                    i++)//recorre los jugadores preguntando si su monto es = a 0 y asignar el prestamo en caso de q ya lo tenga asignado se le da de baja en la partida
            {

                if (lstJugadores.get(i).getMontoDisponible() == 0 && !lstJugadores.get(i).isPrestamoActivo()) {
                    Controlador.darInstancia().mostrarMensaje("100 Fichas Adicionales para " + lstJugadores.get(i).getNombre());
                    lstJugadores.get(i).prestamoFichas();
                    lstJugadores.get(i).setPrestamoActivo(true);
                    if (!lstJugadores.get(i).isActivo()) {
                        lstJugadores.get(i).setActivo(true);
                    }
                } else if (lstJugadores.get(i).getMontoDisponible() == 0 && lstJugadores.get(i).isPrestamoActivo() && lstJugadores.get(i).isSigueEnLaPartida()) {
                    if (!lstJugadores.get(i).isAllIn()) {
                        lstJugadores.get(i).setSigueEnLaPartida(false);
                        Controlador.darInstancia().mostrarMensaje("EL jugado " + lstJugadores.get(i).getNombre() + " No jugara mas en la partida.");
                    }
                }
            }
            mesa.setLstJugadores(mesa.getLstJugadores(), 0);

            iniciarPartida();


        } catch (Exception e) {
        }
    }

    
    public void champion()
    {
        
    }
    
    
    public void ganador(Jugador jugAux)//da como ganada la partida al jugador que se le pasa  y empieza una nueva mano
    {

        try {
            if (mesa.cantFuera() > 1) {
                Controlador.darInstancia().mostrarMensaje("Ha Ganado la mano " + jugAux.getNombre());

                jugAux.setMontoDisponible(mesa.getPozo() + jugAux.getMontoDisponible());
                mesa.setMazo(new Mazo());
                mesa.cambiarDealer(mesa.buscarDealer().getSigJugador());
                mesa.activarJugadores();
                mesa.getLstCartas().removeAll(mesa.getLstCartas());
                mesa.setLstCartas(new ArrayList<Carta>());
                mesa.setPozo(0);
                mesa.setUltimoAp(null);



                List<Jugador> lstJugadores = mesa.getLstJugadores();
                for (int i = 0;
                        i < lstJugadores.size();
                        i++)//recorre los jugadores preguntando si su monto es = a 0 y asignar el prestamo en caso de q ya lo tenga asignado se le da de baja en la partida
                {

                    if (lstJugadores.get(i).getMontoDisponible() == 0 && !lstJugadores.get(i).isPrestamoActivo()) {
                        Controlador.darInstancia().mostrarMensaje("100 Fichas Adicionales para " + lstJugadores.get(i).getNombre());
                        lstJugadores.get(i).prestamoFichas();
                        lstJugadores.get(i).setPrestamoActivo(true);
                        if (!lstJugadores.get(i).isActivo()) {
                            lstJugadores.get(i).setActivo(true);
                        }
                    } else if (lstJugadores.get(i).getMontoDisponible() == 0 && lstJugadores.get(i).isPrestamoActivo() && lstJugadores.get(i).isSigueEnLaPartida()) {

                        if (!lstJugadores.get(i).isAllIn()) {
                            lstJugadores.get(i).setSigueEnLaPartida(false);
                            Controlador.darInstancia().mostrarMensaje("EL jugado " + lstJugadores.get(i).getNombre() + " No jugara mas en la partida.");
                        }
                    }
                }
                mesa.setLstJugadores(mesa.getLstJugadores(), 0);

                iniciarPartida();
            } else {
                terminarPartida(jugAux);
            }

        } catch (Exception e) {
        }
    }

    public void ganadorMasDe2()//da como ganada la partida al jugador que tenga la mejor mano
    {

        try {

            Jugador jugAux = null;
            List<Integer[]> lstRes;
            List<Jugador> lstJugadoresAux = mesa.getLstJugadores();
            List<Jugador> lstJugRes = new ArrayList<>();
            List<Carta> lstCartasMesa = mesa.getLstCartas();
            Integer[] auxRes1 = mesa.buscarSiguienteActivo(lstJugadoresAux.get(0)).identificarMano(lstCartasMesa);
            Integer[] auxRes2;
            lstJugRes.add(mesa.buscarSiguienteActivo(lstJugadoresAux.get(0)));
            mesa.mostrarCartas();





            for (int i = 1; i < lstJugadoresAux.size(); i++) {

                jugAux = lstJugadoresAux.get(i);

                if (jugAux.isSigueEnLaPartida()) {
                    auxRes2 = lstJugadoresAux.get(i).identificarMano(lstCartasMesa);

                    if (auxRes2[0] < auxRes1[0])//si tiene mejor jugada q el otro
                    {
                        auxRes1 = auxRes2;
                        lstJugRes.clear();

                    } else if (auxRes2[0] == auxRes1[0])//si tienen la misma jugada
                    {
                        if (auxRes2[1] == auxRes1[1]) {
                            lstJugRes.add(jugAux);
                        } else if (auxRes2[1] != 1 && auxRes1[1] != 1 && auxRes2[1] > auxRes1[1])//es mayor
                        {
                            auxRes1 = auxRes2;
                            lstJugRes.clear();
                            lstJugRes.add(jugAux);
                        } else if (auxRes2[1] == 1 && auxRes1[1] == 1)//son iguales
                        {
                            lstJugRes.add(jugAux);


                        } else if (auxRes2[1] == 1) //es mayor
                        {
                            auxRes1 = auxRes2;
                            lstJugRes.clear();
                            lstJugRes.add(jugAux);

                        }
                    }
                }
            }
            ganador(lstJugRes);
            //  ganador(jugAux, aux);


        } catch (Exception e) {
        }
    }

    public boolean rondaHumano() {


        Controlador.darInstancia().activarBotones(true);
        return true;
        //se habilitaria los btones para poder apostar, igualar o pasar o retirarse
        //aca es donde pararia el hilo y se esperaria una accion del jugador 
        //que seria un boton q llama a una funcion que aga lo q quiera el humano
        //abrian 4 funciones del humano que realize una accion dependiendo de lo q pida
        //esa funcion siempre tendra q volver a llamar a ronda maquina para seguir el ciclo
    }

    public void humanoAumenta(int monto) {



        if (mesa.apostar(Apostador, monto))//si puede realizar la apuesta
        {
            mesa.setUltimoAp(Apostador);
            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " apostó $" + monto);
            Apostador = mesa.buscarSiguienteActivo(Apostador);
            Controlador.darInstancia().activarBotones(false);
            reengancharEtapa();
        } else {
            Controlador.darInstancia().mostrarMensaje("No tiene Suficientes Fichas Para Aumentar");
        }

        //Usar a Apostador como referencia al humano
        // recibe la cantidad y apuesta 
        // declarar ultimoAp como este humano
        // hace a apostador  igual al siguiente
        // llama a ronda maquina.
    }

    public void reengancharEtapa() {
        switch (Estapa) {
            case "preFlop":
                preFlop(null, true);
                break;
            case "flop":
                flop(true);
                break;
            case "turn":
                turn(true);
                break;
            case "river":
                river(true);
                break;
        }
    }

    public void humanoIguala() {


        if (mesa.apostar(Apostador, mesa.getUltimoAp().getuApuesta())) {
            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " igualo la apuesta");
            Controlador.darInstancia().activarBotones(false);
            Apostador = mesa.buscarSiguienteActivo(Apostador);
            reengancharEtapa();
        } else {
            Controlador.darInstancia().mostrarMensaje("No tiene Suficientes Fichas Para Igualar");
        }
        // se conseigue  la cantidad y apuesta 
        // hace a apostador  igual al siguiente
        // llama a ronda maquina.
    }

    public void humanoPasa() {

        if (buscarAnterior(Apostador).getuApuesta() == 0) {
            Apostador.setuApuesta(0);
            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " Paso");
            Apostador = mesa.buscarSiguienteActivo(Apostador);
            reengancharEtapa();
        } else {
            Controlador.darInstancia().mostrarMensaje("No puede Pasar");
        }

        //pregunta si puede pasar con el metodo del buscarAnterior
        // hace a apostador  igual al siguiente
        // llama a ronda maquina.
    }

    public void humanoRetira() {
        Apostador.setActivo(false);
        Apostador.setAllIn(false);
        mesa.setLstJugadores(mesa.getLstJugadores(), 0);
        Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " abandonó la mano");
        Apostador = mesa.buscarSiguienteActivo(Apostador);
        reengancharEtapa();

        // set activo false al humano y all in en false
        // hace a apostador  igual al siguiente
        // llama a ronda maquina.
    }

    public void humanoAllIn() {
        // juega con all in
        // hace a apostador  igual al siguiente
        // llama a ronda maquina.
    }

    public void reiniciarUltimasApuestas() {
        for (Jugador aux : mesa.getLstJugadores()) {
            aux.setuApuesta(0);
        }
    }

    public boolean rondaMaquina(boolean aux) throws InterruptedException {

        boolean reenganche = aux;

        boolean res = false;
        boolean corriendo = true;
        if (reenganche == false) {

            mesa.setUltimoAp(buscarAnterior(Apostador));

        }
        while (corriendo) {

            res = false;

            if (!Apostador.getNombre().equals(mesa.getUltimoAp().getNombre())) {


                if (Apostador.esHumano()) {

                    corriendo = false;
                    res = rondaHumano();

                } else if (Apostador.isActivo()) {

                    //     Thread.sleep(2000);

                    String accion = Apostador.apuesta(Apostador.identificarMano(mesa.getLstCartas()));//llamo a la estrategia del jugador y le paso el juego que tiene con las cartas de la mesa
                    if (accion.equalsIgnoreCase("aumento")) {

                        Integer apuesta = Apostador.cuantoApostar(Apostador.getMontoDisponible(), mesa.getUltimoAp().getuApuesta());

                        if (mesa.apostar(Apostador, apuesta)) {
                            mesa.setUltimoAp(Apostador);
                            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " apostó $" + apuesta);
                        } else {


                            Apostador.setAllIn(true);
                            Apostador.setActivo(false);
                            mesa.apostar(Apostador, Apostador.getMontoDisponible());
                            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " All In");
                            // all in


                        }
                    } else if (accion.equalsIgnoreCase("igualo")) {
                        if (mesa.apostar(Apostador, mesa.getUltimoAp().getuApuesta())) {
                            Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " igualo la apuesta");
                        } else {
                            if (Apostador.isActivo() == true) {
                                Apostador.setAllIn(true);
                                Apostador.setActivo(false);
                                mesa.apostar(Apostador, Apostador.getMontoDisponible());
                                Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " All In");
                                // all in
                            }

                        }

                    } else if (accion.equalsIgnoreCase("retirarse")) {
                        Apostador.setActivo(false);
                        Apostador.setAllIn(false);
                        Controlador.darInstancia().mostrarMensaje(Apostador.getNombre() + " abandonó la partida");
                    }
                    Apostador = mesa.buscarSiguienteActivo(Apostador);
                } else {
                    Apostador = mesa.buscarSiguienteActivo(Apostador);
                }

            } else {
                corriendo = false;
            }
            if (reenganche == false) {
                mesa.setUltimoAp(mesa.getUltimoAp().getSigJugador());
                reenganche = true;

            }
        }
        return res;
    }

    public Jugador buscarAnterior(Jugador jugAux) {

        Jugador res = jugAux;
        while (true) {
            if (res.getSigJugador().getNombre().equals(jugAux.getNombre())) {
                if (res.getSigJugador().isActivo()) {
                    return res;
                } else {
                    //if (!mesa.getUltimoAp().getNombre().equals(res.getSigJugador().getNombre())) {
                    return buscarAnterior(res.getSigJugador());
                }

            } else {
                res = res.getSigJugador();
            }
        }
    }

    public void ronda(Jugador inicial, String etapa) {

        Jugador apostador = inicial;
        Jugador uApostador = null;
        boolean terminar = false;
        boolean primero = true;//es el control para saber quien es el primero en cada etapa.
        while (terminar == false) {

            if (primero == false) {
                if (apostador.equals(mesa.getUltimoAp())) {
                    terminar = true;
                    mesa.setUltimoAp(mesa.buscarDealer().getSigJugador());

                }
            }

            if (apostador.isActivo() && terminar == false && apostador.isSigueEnLaPartida()) {
                if (apostador.esHumano()) {//si el jugador es humano
                    String accion = Controlador.darInstancia().pedirApuesta();//pide a la interfaz la apuesta a realizar
                    if (accion.equalsIgnoreCase("aumentar")) {
                        Integer apuesta = Controlador.darInstancia().pedirRespuesta(mesa.getUltimoAp().getuApuesta(), apostador.getMontoDisponible());

                        if (mesa.apostar(apostador, apuesta))//si puede realizar la apuesta
                        {
                            uApostador = apostador;
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " apostó $" + apuesta);
                        }
                    } else if (accion.equalsIgnoreCase("igualar")) {
                        if (mesa.apostar(apostador, mesa.getUltimoAp().getuApuesta())) {
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " igualo la apuesta");
                        }

                    } else if (accion.equalsIgnoreCase("pasar")) {
                        if (mesa.apostar(apostador, 0)) {
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " pasó");
                        }
                    } else if (accion.equalsIgnoreCase("retirarse")) {
                        apostador.setSigueEnLaPartida(false);
                        mesa.setLstJugadores(mesa.getLstJugadores(), 0);
                        Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " abandonó la partida");
                    }
                } else//si el jugador es maquina
                {
                    String accion = apostador.apuesta(apostador.identificarMano(mesa.getLstCartas()));//llamo a la estrategia del jugador y le paso el juego que tiene con las cartas de la mesa
                    if (accion.equalsIgnoreCase("aumento")) {

                        Integer apuesta = apostador.cuantoApostar(apostador.getMontoDisponible(), mesa.getUltimoAp().getuApuesta());

                        if (mesa.apostar(apostador, apuesta)) {
                            uApostador = apostador;
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " apostó $" + apuesta);
                        } else {
                            apostador.setActivo(false);
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " SE RETIRA");
                        }
                    } else if (accion.equalsIgnoreCase("igualo")) {
                        if (mesa.apostar(apostador, mesa.getUltimoAp().getuApuesta())) {
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " igualo la apuesta");
                        }

                    } else if (accion.equalsIgnoreCase("retirarse")) {
                        apostador.setSigueEnLaPartida(false);
                        Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " abandonó la partida");
                    } else if (accion.equalsIgnoreCase("pasar")) {
                        if (mesa.apostar(apostador, 0)) {
                            Controlador.darInstancia().mostrarMensaje(apostador.getNombre() + " pasó");
                        }
                    }

                }
            }

            if (mesa.cantActivos()
                    < 2) {
                terminar = true;
            }
            if (uApostador
                    != null) {
                mesa.setUltimoAp(uApostador);
                uApostador = null;
            }
            apostador = apostador.getSigJugador();
            primero = false;


        }
    }

    public void preFlop(Jugador jugCiegaGrande, boolean reenganche) {
        try {

            Jugador dealer = mesa.buscarDealer();

            if (reenganche == false) {
                Estapa = "preFlop";
                Controlador.darInstancia().mostrarMensaje("PREFLOP");
                mesa.repartirCartasJugador(dealer, 2);//se le pasa el dealer y la cantidad de cartas a repartir
                Apostador = mesa.buscarSiguienteActivo(jugCiegaGrande);
            }

            if (rondaMaquina(reenganche) == false) {

                if (mesa.cantActivos() >= 2) {
                    flop(false);
                }
            }



        } catch (Exception e) {
        }
    }

    public void flop(boolean reenganche)//reparte 3 cartas en la mesa y ejecuta una ronda de apuestas
    {
        try {

            Jugador dealer = mesa.buscarDealer();

            if (reenganche == false) {
                mesa.setUltimoAp(mesa.buscarSiguienteActivo(dealer));
                Apostador = mesa.buscarSiguienteActivo(dealer);
                Controlador.darInstancia().mostrarMensaje("FLOP");
                Estapa = "flop";

                mesa.repartirCartasMesa(3);//reparte las 3 cartas comunitarias
                reiniciarUltimasApuestas();
            }

            if (rondaMaquina(reenganche) == false) {

                if (mesa.cantActivos() >= 2) {
                    turn(false);
                } else {
                    //aca se fija quien es el ganador.
                }
            }


        } catch (Exception e) {
        }
    }

    public void turn(boolean reenganche) {
        try {
            Jugador dealer = mesa.buscarDealer();

            if (reenganche == false) {
                mesa.setUltimoAp(mesa.buscarSiguienteActivo(dealer));
                Apostador = mesa.buscarSiguienteActivo(dealer);
                Controlador.darInstancia().mostrarMensaje("TURN");
                Estapa = "turn";
                mesa.repartirCartasMesa(1);
                reiniciarUltimasApuestas();

            }
            if (rondaMaquina(reenganche) == false) {

                if (mesa.cantActivos() >= 2) {
                    river(false);
                } else {
                    //aca se fija quien es el ganador.
                }
            }

        } catch (Exception e) {
        }

    }

    public void river(boolean reenganche) {
        try {
            Jugador dealer = mesa.buscarDealer();
            if (reenganche == false) {
                mesa.setUltimoAp(mesa.buscarSiguienteActivo(dealer));
                Apostador = mesa.buscarSiguienteActivo(dealer);
                Controlador.darInstancia().mostrarMensaje("RIVER");
                Estapa = "river";
                mesa.repartirCartasMesa(1);
                reiniciarUltimasApuestas();

            }
            if (rondaMaquina(reenganche) == false) {

                if (mesa.cantActivos() >= 2) {
                    //aca se fija quien es el ganador mas de 2 
                } else {
                    //aca se fija quien es el ganador.
                }
            }

        } catch (Exception e) {
        }
    }
}
